/*
 ============================================================================
 Name        : BitwiseGuys_Scheduler.c
 Author      : Dallas Rosson, Joshua Warner, Tyson Lewis, Ken Norton
 Team        : Bitwise Guys
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Process types
#define UI 0
#define CALCULATE 1
#define PRODUCER 2
#define CONSUMER 3

/**
 * 1 - locked
 * 0 - available
 * */
int MemMutexLock;
int MAX_MEM = 10000;

// The main structure for the processes.
int *processes;

// The main structure for the PCBs.
int *PCBs;

typedef struct process_str {
	int	no_steps;		// number of time steps before resetting to 0 - number of instructions
	int no_requests;	// number of requests that will be generated during the process run
	int * requests;		// an array of requests, each request (e.g. io service) is issued at a specific
	// time step. These are the synchronous events that result in traps being issued.
	// You can get fancy and make this an array of RequestTypeStr which contains the
	// step number when issued, and a request type (e.g. 0=io, 1=sync, etc.)
	int type;

} ProcessStr;

typedef struct pcb_str {
	int	pid;
	int next_step;		// this is the step count that the CPU had gotten to when this process was
	// prempted (like a PC register value)
	int state;			// e.g. 0=running, 1=ready, 2=interrupted, 3=blocked
	ProcessStr proc;    // pointer to the actual process
	int waiting_on;		// which queue is it in if it is waiting on something (blocked)
	int owns;			// which mutex lock does it own
	// anything else you need
} PCBStr;

/**
 * Struct for registers
 * **/
typedef struct register_str {
	//TODO some data structure to hold? PCB
}Register_str;

/**Struct for the shared memory
 *
 */
typedef struct sharedMemory_str {
	int SharedMemory;
}SharedMemory_str;


/**
 * Processor functions
 * ******************************************************************************
 */

/**
 * Fill an array with processes.
 */
void proc_createProcesses(char * args) {
	// TODO:
	// read command line args
	// initialize array of processes
	// initialize PCB array: the index from the processes array is the PID.

	char command[20];
	int type;

	if (strcmp(command, "UI")) {
		type = UI;
	} else if (strcmp(command, "CALCULATE")) {
		type = CALCULATE;
	} else if (strcmp(command, "PRODUCER")) {
		type = PRODUCER;
	} else if (strcmp(command, "CONSUMER")) {
		type = CONSUMER;
	}

//	proc_createProcess(type);
}
/*
ProcessStr proc_createProcess(int type) {
	// TODO: Update function with appropriate assignments for the variables.
	ProcessStr proc;
	proc.type = type;
	proc.no_steps = 0;
	proc.no_requests = 0;
	proc.requests = (int) malloc(sizeof(int) * proc.no_requests);

	int i;
	for (i = 0; i < proc.no_requests; i++) {
		*proc.requests[i] = 0;
	}

	return proc;
}
*/
/**
 * UI process.
 */
void proc_UI(PCBStr * pcb) {
	// get keyboard input
}

/**
 * CALCULATING process.
 */
void proc_CALCULATE(PCBStr * pcb) {
	// calculate something
}

/**
 * PRODUCER process.
 */
void proc_PRODUCER(PCBStr * pcb) {

}

/**
 * CONSUMER process.
 */
void proc_CONSUMER(PCBStr * pcb) {

}

/**
 * Runs the process that is stored in the given PCB.
 */
/*
void proc_run(PCBStr * pcb) {
	switch (pcb->proc.type) {
	case UI:
		proc_UI(PCBStr * pcb);
		break;
	case CALCULATE:
		proc_CALCULATE(PCBStr * pcb);
		break;
	case PRODUCER:
		proc_PRODUCER(PCBStr * pcb);
		break;
	case CONSUMER:
		proc_CONSUMER(PCBStr * pcb);
		break;
	}
}
*/
/**CPU Helper functions**/
/********************************************************************************/
/**
 * Timer interrupt handler gets called when the time slice is up
 * **/
void timer_int_handler(){
	//TODO place the current running process in the end of the ready queue
}
/**
 * io interrupt handler gets called when an io interrupt occurs.
 * **/
void io_int_handler(){
	//TODO handle the interrupt and handle the current process in the waiting io blocking queue.

}
/**
 * io request handler gets called when an io request occurs.
 * **/
void io_req_trap_handler(){
	//TODO place the current process interrupt the io blocking queue
}
/**
 *
 * Trap to acquire the Mutex
 * **/
void mutex_acquire_trap_handler(){
	//TODO acquire the mutex if possible, if not place in the Mutex waiting queue.
}

/**
 *
 * Trap to give up the mutex.
 * **/
void mutex_give_trap_handler(){
	//TODO give up the mutex and ??? Process is finished

}
/**
 * Trap to try to write to memory, if the write lock is available
 *
 * */
void memory_write_trap_hanlder(){
	//TODO code to write to the shared memory location should lock the read mutex/semiphore
	//if it cannot write then it is placed in the blocking queue until the lock is available.
}

/**
 * Trap to try to read to memory, if the mutex lock is available
 * Calls the system_call() to read memory
 * */
void memory_read_trap_hanlder(){
	//TODO code to read to the shared memory location should lock the read mutex/semiphore

}
/**
 * System call to actually do the io opperation.
 *
 * */
void io_system_call(){
	//TODO code to do the io get or display io
}
/**
 * System call to actually do the mutex get opperation.
 *
 * */
void mutex_acquire_system_call(){
	//TODO code to get mutex
}
/**
 * System call to actually do the mutex give opperation.
 *
 * */
void mutex_give_system_call(){
	//TODO code to give the mutex
}
/**
 * System call to actually do the memory write opperation.
 * @param takes a parameter of the data to be written
 * */
void memory_write_system_call(){
	//TODO write Data
}
/**
 * System call to actually do the memory read opperation.
 * @return returns the data in memory.
 * */
int memory_read__system_call(){
	int result;
	return result;
}




void KernalSpace(int handler){

	switch (handler){
	case 0: timer_int_handler();
	break;
	case 1: io_int_handler();
	break;
	case 2: io_req_trap_handler();
	break;
	case 3: mutex_acquire_trap_handler();
	break;
	case 4: mutex_give_trap_handler();
	break;
	case 5: memory_write_trap_hanlder();
	break;
	case 6: memory_read_trap_hanlder();
	break;

	}

}

void UserSpace(int systemCall){
	int data = 0;
	switch (systemCall){
	case 0: io_system_call();
	break;
	case 1: mutex_acquire_system_call();
	break;
	case 2: mutex_give_system_call();
	break;
	case 3: memory_write_system_call();
	break;
	case 4: memory_read__system_call();
	break;

	}
}
void CPU(){
	int step;
	/**Registers*/
	while (!step == MAX_MEM){

		/**CPU Object?*/
		/**System Timer*/

		step++;
	}




}




int main(void) {
	printf("Hello World");
	CPU();
	//TODO Project 2
	return 0;
}
